package cn.ad.server.persistence;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

import javax.annotation.Resource;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.joda.time.DateTime;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.stereotype.Repository;

import cn.ad.server.common.exception.BasicInfoException;
import cn.ad.server.common.utils.IPUtils;
import cn.ad.server.persistence.dao.SysConfigDao;
import cn.ad.server.domain.SysConfig;

@Repository
public class ConfigRepositoryImpl implements ConfigRepository {

	static final Logger logger = LoggerFactory.getLogger(ConfigRepositoryImpl.class);

	@Autowired
	private SysConfigDao sysConfigDao;

	static ConcurrentMap<String, String> nativeCache = new ConcurrentHashMap<String, String>();

	@Resource(name = "cacheRedisTemplate")
	private HashOperations<String, String, String> configHashOperations;

	// @Override
	public String fetchHostName() {
		String key = "host.name";
		String value = nativeCache.get(key);
		if (StringUtils.isEmpty(value)) {
			value = IPUtils.getHostName();
			nativeCache.put(key, value);
		}
		if (StringUtils.isEmpty(value))
			throw new BasicInfoException("Host Name is Empty");
		return value;
	}

	String fetch(String key, boolean throwable) {
		String lastTimeKey = key + ".time";
		String lastTimeValue = nativeCache.get(lastTimeKey);
		String value = nativeCache.get(key);
		DateTime now = DateTime.now();
		DateTime lastTime = StringUtils.isBlank(lastTimeValue) ? now : DateTime.parse(lastTimeValue);
		long mDiff = (now.getMillis() - lastTime.getMillis()) / 1000 / 60;
		if (StringUtils.isEmpty(value) || mDiff >= 5) {
			value = configHashOperations.get(SysConfig.CACHE_NAME, key);
			if (StringUtils.isEmpty(value))
				return "";
			nativeCache.put(key, value);
			nativeCache.put(lastTimeKey, now.toString());
		}
		if (StringUtils.isEmpty(value) && throwable)
			throw new BasicInfoException(key + " Config is Empty");
		return value;
	}

	// @Override
	public Integer fetchServerNumber() {
		String key = "server.amount";
		String value = fetch(key, true);
		return Integer.valueOf(value);
	}

	@Override
	public void warmAllConfig() {
		List<SysConfig> configs = sysConfigDao.findAll();
		if (CollectionUtils.isEmpty(configs))
			return;
		for (SysConfig config : configs) {
			if (config.getStatus() == 1)
				configHashOperations.put(SysConfig.CACHE_NAME, config.getConfigKey(), config.getConfigValue());
			else if (config.getStatus() != 1)
				configHashOperations.delete(SysConfig.CACHE_NAME, config.getConfigKey());
		}
	}
	
	@Override
	public Map<String, String> fetchAllConfig() {
		return configHashOperations.entries(SysConfig.CACHE_NAME);
	}

	@Override
	public int fetchGuidClickLimit() {
		String key = "guid.click.limit";
		String value = fetch(key, false);
		if (StringUtils.isEmpty(value))
			return 1;
		return Integer.valueOf(value);
	}

	@Override
	public int fetchUserAndCreativeClickLimit() {
		String key = "user.creative.click.limit";
		String value = fetch(key, false);
		if (StringUtils.isEmpty(value))
			return 1;
		return Integer.valueOf(value);
	}

	@Override
	public int fetchGuidImpressionsLimit() {
		String key = "guid.impressions.limit";
		String value = fetch(key, false);
		if (StringUtils.isEmpty(value))
			return 1;
		return Integer.valueOf(value);
	}

	@Override
	public int fetchUserAndCreativeImpressionsLimit() {
		String key = "user.creative.impressions.limit";
		String value = fetch(key, false);
		if (StringUtils.isEmpty(value))
			return 1;
		return Integer.valueOf(value);
	}

	@Override
	public long fetchGuidTimeout(int channelId) {
		String key = new StringBuffer("guid.timeout.channel.").append(channelId).toString();
		String value = fetch(key, false);
		if (StringUtils.isEmpty(value))
			return 30;
		return Integer.valueOf(value);
	}

	@Override
	public List<String> fetchAllHostName() {
		String key = "all.host.name";
		String value = fetch(key, false);
		if (StringUtils.isEmpty(value))
			return new ArrayList<String>();
		return Arrays.asList(value.split(";"));
	}

	@Override
	public int fetchTimeBucket() {
		String key = "time.bucket.spec";
		String value = fetch(key, false);
		if (StringUtils.isEmpty(value))
			return 30;
		return Integer.valueOf(value);
	}

	@Override
	public int fetchFilterRatio() {
		String key = "filter.ratio";
		String value = fetch(key, false);
		if (StringUtils.isEmpty(value))
			return 10;
		return Integer.valueOf(value);
	}

	@Override
	public List<String> fetchExcludeCampaign() {
		String key = "exclude.campaign";
		String value = fetch(key, false);
		if (StringUtils.isEmpty(value))
			return new ArrayList<String>();
		return Arrays.asList(value.split(","));
	}

	@Override
	public List<String> fetchMonitoredStrategy() {
		String key = "monitored.strategy";
		String value = fetch(key, false);
		if (StringUtils.isEmpty(value))
			return new ArrayList<String>();
		return Arrays.asList(value.split(","));
	}

	@Override
	public boolean fetchDebugMode() {
		String key = "debug.mode";
		String value = fetch(key, false);
		if (StringUtils.isEmpty(value))
			return false;
		return Boolean.valueOf(value);
	}

	@Override
	public List<String> fetchMonitoredAdSpace() {
		String key = "monitored.adspace";
		String value = fetch(key, false);
		if (StringUtils.isEmpty(value))
			return new ArrayList<String>();
		return Arrays.asList(value.split(","));
	}
	@Override
	public long fetchDeviceIdTimeout() {
		String key = "deviceid.timeout";
		String value = fetch(key, false);
		if (StringUtils.isEmpty(value))
			return 30;
		return Long.valueOf(value);
	}
	
	@Override
	public String fetchDeviceActivePolicy() {
		String key = "device.active.policy.selected.firstorlast";
		String value = fetch(key, false);
		return value;
	}

}
